package com.qf.service.imp;

import com.qf.entity.*;
import com.qf.feign.CityFeign;
import com.qf.feign.HotalFeign;
import com.qf.service.ISearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.data.elasticsearch.core.query.UpdateResponse;
import org.springframework.stereotype.Service;

import java.rmi.MarshalledObject;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class SearchServiceImpl implements ISearchService {
    @Autowired
    private ElasticsearchRestTemplate restTemplate;
    @Autowired
    private CityFeign cityFeign;
    @Autowired
    private HotalFeign hotalFeign;

    @Override
    public boolean createIndex() {
        IndexOperations indexOps = restTemplate.indexOps(Hotal.class);
        if(!indexOps.exists()){
            indexOps.create();

            Document mapping = indexOps.createMapping();

            indexOps.putMapping(mapping);

            syncDatabase();

            return true;
        }

        return false;
    }

    @Override
    public boolean deleteIndex() {
        IndexOperations indexOps = restTemplate.indexOps(Hotal.class);

        return indexOps.exists() ? indexOps.delete() : false;
    }

    @Override
    public void syncDatabase() {
        R<List<Hotal>> hotals = hotalFeign.list();

        hotals.getData().stream().forEach(
                hotal -> {
                    R<City> cityR = cityFeign.queryCityById(hotal.getCid());
                    hotal.setCity(cityR.getData());
                    restTemplate.save(hotal);
                }
        );
    }

    @Override
    public int insertHotal(Hotal hotal) {
        R<City> cityR = cityFeign.queryCityById(hotal.getCid());
        hotal.setCity(cityR.getData());
        restTemplate.save(hotal);
        return 1;
    }

    @Override
    public boolean insertRoom(Room room) {
        Map<String,Object> roomMap = new HashMap<>();
        roomMap.put("id",room.getId());
        roomMap.put("hid",room.getHid());
        roomMap.put("info",room.getInfo());
        roomMap.put("title",room.getTitle());
        roomMap.put("number",room.getNumber());
        roomMap.put("prices",new ArrayList<>());

        Map<String ,Object> params = new HashMap<>();
        params.put("myroom",roomMap);

        UpdateQuery updateQuery = UpdateQuery.builder(room.getHid()+"")
                .withScript("ctx._source.rooms.add(params.myroom)")
                .withParams(params)
                .build();
        UpdateResponse resp = restTemplate.update(updateQuery, IndexCoordinates.of("hotal_index"));
        return resp.getResult() == UpdateResponse.Result.UPDATED;
    }

    @Override
    public int insertRoomPrice(Integer hid, List<RoomPrice> roomPrices) {
        List<UpdateQuery> updateQueryList = new ArrayList<>();
        roomPrices.stream().forEach(roomPrice -> {

            Map<String,Object> roomPriceMap = new HashMap<>();
            roomPriceMap.put("id",roomPrice.getId());
            roomPriceMap.put("rid",roomPrice.getRid());
            roomPriceMap.put("date",roomPrice.getDate().getTime());
            roomPriceMap.put("price",roomPrice.getPrice());
            roomPriceMap.put("number",roomPrice.getNumber());
            roomPriceMap.put("hasnumber",roomPrice.getHasNumber());


            Map<String ,Object> myparams = new HashMap<>();

            myparams.put("rid",roomPrice.getRid());
            myparams.put("myprice",roomPriceMap);

            UpdateQuery updateQuery = UpdateQuery.builder(hid+"")
                    .withScript("for(r in ctx._source.rooms){ if(r.id == params.id) { r.prices.add(params.myprice) }}")
                    .withParams(myparams)
                    .build();
            updateQueryList.add(updateQuery);
        });
        restTemplate.bulkUpdate(updateQueryList,IndexCoordinates.of("hotal_index"));

        return 1;
    }

    @Override
    public int updateRoomPrice(Integer hid, RoomPrice roomPrice) {
        Map<String,Object> params = new HashMap<>();
        params.put("rid",roomPrice.getId());
        params.put("rpid",roomPrice.getRid());
        params.put("price",roomPrice.getPrice());

        UpdateQuery updateQuery = UpdateQuery.builder(hid+"")
                .withScript("for(r in ctx._source.rooms){ if(r.id == params.rid){for(rp in r.prices){ if(rp.id == params.rpid) {rp.price = params.price} }} }")
                .withParams(params)
                .build();

        UpdateResponse resp = restTemplate.update(updateQuery, IndexCoordinates.of("hotal_index"));

        return 1;
    }

    @Override
    public List<Hotal> searchHotalList(SearchParams searchParams) {
        return null;
    }

    @Override
    public int updateRoomNumber(PricesParams pricesParams) {
        String painless = "for(room in ctx._source.rooms){" +
                "if(room.id == params.rid){" +
                "for(roomprice in room.prices){" +
                "if(roomprice.date >= params.beginTime && roomprice.date < params.endTime){" +
                "roomprice.number += params.rnumber" +
                "}" +
                "}" +
                "}" +
                "}";

        Map<String, Object> params = new HashMap<>();

        params.put("rid",pricesParams.getRid());
        params.put("beginTime",pricesParams.getBeginTime().getTime());
        params.put("endTime",pricesParams.getEndTime().getTime());
        params.put("rnumber",pricesParams.getRnumber());

        UpdateQuery updateQuery = UpdateQuery.builder(pricesParams.getHid()+"")
                .withScript(painless)
                .withParams(params)
                .build();

        restTemplate.update(updateQuery,IndexCoordinates.of("hotal_index"));

        System.out.println("下单同步成功");

        return 1;
    }
}
